#include <assert.h>
#include <time.h>
#include "SdlJeu.h"

const int TAILLE_SPRITE=34;

SDL_Surface *SDL_load_image(const char* filename );
void SDL_apply_surface( SDL_Surface* source, SDL_Surface* destination, int x, int y );



void sdljeuInit(SdlJeu* sdljeu,int niv)
{
	Jeu *jeu;
	int dimx, dimy;

	jeu = &(sdljeu->jeu);
	jeuInit(jeu,niv);

	assert(   SDL_Init( SDL_INIT_EVERYTHING )!= -1 );

	dimx = terGetDimx( jeuGetTerrain(jeu))+3;
	dimy = terGetDimy( jeuGetTerrain(jeu));
	dimx = dimx * TAILLE_SPRITE;
	dimy = dimy * TAILLE_SPRITE;
	sdljeu->surface_ecran = SDL_SetVideoMode(   dimx, dimy, 32, SDL_SWSURFACE );
	assert(sdljeu->surface_ecran!=NULL);
	SDL_WM_SetCaption( "battle_city_tank v0.1", NULL );

	sdljeu->surface_tankh = SDL_load_image("data/tankh.bmp");
	if (sdljeu->surface_tankh==NULL)
		sdljeu->surface_tankh = SDL_load_image("../data/tankh.bmp");
	assert(sdljeu->surface_tankh!=NULL);

	sdljeu->surface_tankb = SDL_load_image("data/tankb.bmp");
	if (sdljeu->surface_tankb==NULL)
		sdljeu->surface_tankb= SDL_load_image("../data/tankb.bmp");
	assert(sdljeu->surface_tankb!=NULL);

	sdljeu->surface_bonus=SDL_load_image("data/bonus.bmp");
	if(sdljeu->surface_bonus==NULL)
        sdljeu->surface_bonus= SDL_load_image("../data/bonus.bmp");
    assert(sdljeu->surface_bonus!=NULL);

	sdljeu->surface_tankg= SDL_load_image("data/tankg.bmp");
	if (sdljeu->surface_tankg==NULL)
		sdljeu->surface_tankg = SDL_load_image("../data/tankg.bmp");
	assert(sdljeu->surface_tankg!=NULL);

	sdljeu->surface_tankd = SDL_load_image("data/tankd.bmp");
	if (sdljeu->surface_tankd==NULL)
		sdljeu->surface_tankd = SDL_load_image("../data/tankd.bmp");
	assert(sdljeu->surface_tankd!=NULL);

	sdljeu->surface_cle=SDL_load_image("data/cle.bmp");
	if(sdljeu->surface_cle==NULL)
        sdljeu->surface_cle=SDL_load_image("../data/cle.bmp");
    assert(sdljeu->surface_cle!=NULL);


	sdljeu->surface_base=SDL_load_image("data/base.bmp");
	if(sdljeu->surface_base==NULL)
        sdljeu->surface_base=SDL_load_image("../data/base.bmp");
    assert(sdljeu->surface_base!=NULL);


	sdljeu->surface_gameover=SDL_load_image("data/battle_city_tank.bmp");
	if(sdljeu->surface_gameover==NULL)
        sdljeu->surface_gameover=SDL_load_image("../data/battle_city_tank.bmp");
    assert(sdljeu->surface_gameover!=NULL);

	sdljeu->surface_vie=SDL_load_image("data/vie.bmp");
	if(sdljeu->surface_vie==NULL)
        sdljeu->surface_vie=SDL_load_image("../data/vie.bmp");
    assert(sdljeu->surface_vie!=NULL);

	sdljeu->surface_mur = SDL_load_image("data/mur.bmp");
	if (sdljeu->surface_mur==NULL)
		sdljeu->surface_mur = SDL_load_image("../data/mur.bmp");
	assert(sdljeu->surface_mur!=NULL);

	sdljeu->surface_acier=SDL_load_image("data/acier.bmp");
	if(sdljeu->surface_acier==NULL)
        sdljeu->surface_acier=SDL_load_image("../data/acier.bmp");
    assert(sdljeu->surface_acier!=NULL);

    sdljeu->surface_camouflage=SDL_load_image("data/murb.bmp");
    if(sdljeu->surface_camouflage==NULL)
        sdljeu->surface_camouflage=SDL_load_image("../data/murb.bmp");
    assert(sdljeu->surface_camouflage!=NULL);

	sdljeu->surface_ennemib= SDL_load_image("data/ennemib.bmp");
	if (sdljeu->surface_ennemib==NULL)
		sdljeu->surface_ennemib = SDL_load_image("../data/ennemib.bmp");
	assert(sdljeu->surface_ennemib!=NULL);

	sdljeu->surface_ennemih= SDL_load_image("data/ennemih.bmp");
	if(sdljeu->surface_ennemih==NULL)
        sdljeu->surface_ennemih=SDL_load_image("../data/ennemih.bmp");
    assert(sdljeu->surface_ennemih!=NULL);

    sdljeu->surface_ennemig= SDL_load_image("data/ennemig.bmp");
	if(sdljeu->surface_ennemig==NULL)
        sdljeu->surface_ennemig=SDL_load_image("../data/ennemig.bmp");
    assert(sdljeu->surface_ennemig!=NULL);

    sdljeu->surface_ennemid= SDL_load_image("data/ennemid.bmp");
	if(sdljeu->surface_ennemid==NULL)
        sdljeu->surface_ennemid=SDL_load_image("../data/ennemid.bmp");
    assert(sdljeu->surface_ennemid!=NULL);

	sdljeu->surface_tousEnnemi=SDL_load_image("data/ennemi.bmp");
	if(sdljeu->surface_tousEnnemi==NULL)
        sdljeu->surface_tousEnnemi=SDL_load_image("../data/ennemi.bmp");
    assert(sdljeu->surface_tousEnnemi!=NULL);

	sdljeu->surface_tir=SDL_load_image("data/tir1.bmp");
	if(sdljeu->surface_tir==NULL)
        sdljeu->surface_tir=SDL_load_image("../data/tir1.bmp");
    assert(sdljeu->surface_tir!=NULL);
}

/**@brief Procedure sdljeuAff:
<B>sdljeuAff affiche le jeu actuel dans une window(fenetre),
c'est à dire le terrain avec les murs,les espace,le tank,les ennemis
 et le tir avec les images qui ont été chargées </B> */
void sdljeuAff(SdlJeu *sdljeu)
{
	int x,y,i_enem,i_tir,j,k,nbennemitotale,nbvie;

    const Jeu *jeu = &(sdljeu->jeu);
	const Terrain *ter = jeuGetTerrain(jeu);
	const Tank *tank = jeuGetTank(jeu);
	const Tir* tirtank=jeuGetConstTir(jeu);
	nbennemitotale=0;
	nbvie=tankGetVie(tank);

	/* Remplir l'écran de noir */
	SDL_FillRect(sdljeu->surface_ecran, &sdljeu->surface_ecran->clip_rect, SDL_MapRGB(sdljeu->surface_ecran->format, 0000, 0000, 0000 ) );

    if(tank->tank_vie==0)
    {
        SDL_apply_surface(sdljeu->surface_gameover,sdljeu->surface_ecran,0,0);
    }
	for (x=0;x<terGetDimx(ter);++x)
	{
        for (y=0;y<terGetDimy(ter);++y)
        {
            if (terGetXY(ter,x,y)=='#')
            {
                SDL_apply_surface(sdljeu->surface_mur, sdljeu->surface_ecran, x*TAILLE_SPRITE, y*TAILLE_SPRITE);
            }
            if(terGetXY(ter,x,y)=='A')
            {
                SDL_apply_surface(sdljeu->surface_acier,sdljeu->surface_ecran,x*TAILLE_SPRITE,y*TAILLE_SPRITE);
            }
            if(terGetXY(ter,x,y)=='B')
            {
                SDL_apply_surface(sdljeu->surface_base,sdljeu->surface_ecran,x*TAILLE_SPRITE,y*TAILLE_SPRITE);
            }
            else if(terGetXY(ter,x,y)=='V')
                {
                    SDL_apply_surface(sdljeu->surface_camouflage,sdljeu->surface_ecran,x*TAILLE_SPRITE,y*TAILLE_SPRITE);
                }
        }
	}
    for (i_enem=0; i_enem<jeu->jeu_nbennemi; i_enem++)
    {
        if(terGetXY(ter,jeu->jeu_tabennemi.ad[i_enem].enem_x,jeu->jeu_tabennemi.ad[i_enem].enem_y)!='V')
        {
            if(jeu->jeu_tabennemi.ad[i_enem].enem_direction==0)
            {
                SDL_apply_surface(sdljeu->surface_ennemig,sdljeu->surface_ecran,(jeu->jeu_tabennemi.ad[i_enem].enem_x)*TAILLE_SPRITE, (jeu->jeu_tabennemi.ad[i_enem].enem_y)*TAILLE_SPRITE);
            }
            if(jeu->jeu_tabennemi.ad[i_enem].enem_direction==1)
            {
                SDL_apply_surface(sdljeu->surface_ennemid,sdljeu->surface_ecran,(jeu->jeu_tabennemi.ad[i_enem].enem_x)*TAILLE_SPRITE, (jeu->jeu_tabennemi.ad[i_enem].enem_y)*TAILLE_SPRITE);
            }
            if(jeu->jeu_tabennemi.ad[i_enem].enem_direction==2)
            {
                SDL_apply_surface(sdljeu->surface_ennemib,sdljeu->surface_ecran,(jeu->jeu_tabennemi.ad[i_enem].enem_x)*TAILLE_SPRITE, (jeu->jeu_tabennemi.ad[i_enem].enem_y)*TAILLE_SPRITE);
            }
            if(jeu->jeu_tabennemi.ad[i_enem].enem_direction==3)
            {
                SDL_apply_surface(sdljeu->surface_ennemih,sdljeu->surface_ecran,(jeu->jeu_tabennemi.ad[i_enem].enem_x)*TAILLE_SPRITE, (jeu->jeu_tabennemi.ad[i_enem].enem_y)*TAILLE_SPRITE);
            }
        }
    }

	/* Copier le sprite du tank sur l'écran */
	if(terGetXY(ter,tank->tank_x,tank->tank_y)!='V')
	{
       if(tank->tank_direction==0)
       {
            SDL_apply_surface(sdljeu->surface_tankg,sdljeu->surface_ecran,tankGetX(tank)*TAILLE_SPRITE,tankGetY(tank)*TAILLE_SPRITE );
       }
       if(tank->tank_direction==1)
       {
            SDL_apply_surface(sdljeu->surface_tankd,sdljeu->surface_ecran,tankGetX(tank)*TAILLE_SPRITE,tankGetY(tank)*TAILLE_SPRITE);
       }
       if(tank->tank_direction==2)
       {
            SDL_apply_surface(sdljeu->surface_tankb,sdljeu->surface_ecran,tankGetX(tank)*TAILLE_SPRITE,tankGetY(tank)*TAILLE_SPRITE);
       }
       if(tank->tank_direction==3)
       {
            SDL_apply_surface(sdljeu->surface_tankh,sdljeu->surface_ecran,tankGetX(tank)*TAILLE_SPRITE,tankGetY(tank)*TAILLE_SPRITE);
       }
	}

	/*copier le sprite du tir du tank sur l'ecran*/
	if(jeu->jeu_tank.tank_projectile==1)
	{
        SDL_apply_surface(sdljeu->surface_tir,sdljeu->surface_ecran,tirGetX(tirtank)*TAILLE_SPRITE,tirGetY(tirtank)*TAILLE_SPRITE);
	}

	/* copier le sprite des tirs ennemis lancé sur l'ecran */
	for(i_tir=0;i_tir<jeu->jeu_nbtirennemi;i_tir++)
	{
        SDL_apply_surface(sdljeu->surface_tir,sdljeu->surface_ecran,(jeu->jeu_tabtirennemi.ad[i_tir].tir_x)*TAILLE_SPRITE, (jeu->jeu_tabtirennemi.ad[i_tir].tir_y)*TAILLE_SPRITE);
	}
	for(j=0;j<7;j++)
	{
        for(k=ter->dimx;k<ter->dimx+3;k++)
        {
            if(nbennemitotale>jeu->jeu_nbennemitotale)
            {
                break;
            }
            else if(jeu->jeu_nbennemitotale>0)
            {
                SDL_apply_surface(sdljeu->surface_tousEnnemi,sdljeu->surface_ecran,k*TAILLE_SPRITE,j*TAILLE_SPRITE);
                nbennemitotale++;
            }
        }
	}
	for(j=ter->dimy-4;j<ter->dimy;j++)
	{
        for(k=ter->dimx;k<ter->dimx+3;k++)
        {
           if(nbvie==0)
           {
                break;
           }
           else
           {
                SDL_apply_surface(sdljeu->surface_vie,sdljeu->surface_ecran,k*TAILLE_SPRITE,j*TAILLE_SPRITE);
                nbvie--;
           }
        }
	}
	if(jeu->jeu_bonus==1)
	{
        SDL_apply_surface(sdljeu->surface_bonus,sdljeu->surface_ecran,jeuGetAbscisseBonus(jeu)*TAILLE_SPRITE,jeuGetOrdonneeBonus(jeu)*TAILLE_SPRITE);
	}
	if(jeu->jeu_cle==1)
	{
        SDL_apply_surface(sdljeu->surface_cle,sdljeu->surface_ecran,jeuGetAbscisseCle(jeu)*TAILLE_SPRITE,jeuGetOrdonneeCle(jeu)*TAILLE_SPRITE);
	}

}

void sdljeuBoucle(SdlJeu* sdljeu)
{
	SDL_Event event;
	int niv=jeuGetNiveau(&sdljeu->jeu);
	int vie,score,temp_forcetir,temp_cle,i;
	 int rafraichissement,tmp;
    /* Horloges (en secondes) */
    float horloge_courante, horloge_precedente;

    /* Intervalle de temps (en secondes) entre deux évolutions du jeu */
    /* Changer la valeur pour ralentir ou accélérer le déplacement des tank ennemis */
    float intervalle_horloge = 0.1f;
    int continue_boucle = 1;
	i=rand()%5;
	sdljeu->jeu.jeu_xbonus=i+1+rand()%sdljeu->jeu.jeu_terrain.dimx/2;
	sdljeu->jeu.jeu_ybonus=i+2+rand()%sdljeu->jeu.jeu_terrain.dimy/2;
	sdljeu->jeu.jeu_xcle=i+1+rand()%sdljeu->jeu.jeu_terrain.dimx;
	sdljeu->jeu.jeu_ycle=i+1+rand()%sdljeu->jeu.jeu_terrain.dimy;
    temp_forcetir=10;
	temp_cle=10;
	sdljeuAff(sdljeu);
	assert( SDL_Flip( sdljeu->surface_ecran )!=-1 );

    /* Récupère l'horloge actuelle et la convertit en secondes */
    /* clock() retourne le nombre de tops horloge depuis le lancement du programme */
    horloge_precedente = (float)clock()/(float)CLOCKS_PER_SEC;

	/* Tant que ce n'est pas la fin ... */
	while ( continue_boucle == 1 )
	{
	    rafraichissement = 0;

	     /* Récupère l'horloge actuelle et la convertit en secondes */
        horloge_courante = (float)clock()/(float)CLOCKS_PER_SEC;


        /* Si suffisamment de temps s'est écoulé depuis la dernière prise d'horloge */
        if (horloge_courante-horloge_precedente>=intervalle_horloge)
        {
                tmp=tankGetTemp(&sdljeu->jeu.jeu_tank);
                tmp=-tmp;
                tankSetTemp(&sdljeu->jeu.jeu_tank,tmp);
                jeuEvolue(&(sdljeu->jeu));
                rafraichissement = 1;
                horloge_precedente = horloge_courante;
                temp_forcetir=temp_forcetir-1;
                temp_cle=temp_cle-1;
        }

		/* tant qu'il y a des evenements à traiter : cette boucle n'est pas bloquante */
		while ( SDL_PollEvent( &event ) )
		{
			/* Si l'utilisateur a cliqué sur la croix de fermeture */
			if ( event.type == SDL_QUIT )
				continue_boucle = 0;

			/* Si l'utilisateur a appuyé sur une touche */
			if ( event.type == SDL_KEYDOWN )
			{
				switch ( event.key.keysym.sym )
				{
				case SDLK_UP:
					jeuActionClavier(&(sdljeu->jeu), 'h');
					rafraichissement = 1;
					break;
				case SDLK_DOWN:
					jeuActionClavier(&(sdljeu->jeu), 'b');
					rafraichissement = 1;
					break;
				case SDLK_LEFT:
					jeuActionClavier(&(sdljeu->jeu), 'g');
					rafraichissement = 1;
					break;
				case SDLK_RIGHT:
					jeuActionClavier(&(sdljeu->jeu), 'd');
					rafraichissement = 1;
					break;
                case SDLK_x:
                    jeuActionClavier(&sdljeu->jeu,'x');
                    rafraichissement=1;
				default: break;
				}
			}

		}
		if(sdljeu->jeu.jeu_tank.tank_vie==0)
		{
            continue_boucle=0;
		}
		if(temp_forcetir==0)
		{
            sdljeu->jeu.jeu_tank.tank_forcetir=0;
            temp_forcetir=80;
		}
		if(temp_cle==0)
		{
            sdljeu->jeu.jeu_tank.tank_baseok=0;
            temp_cle=80;
		}

        if (rafraichissement==1)
        {
            if(sdljeu->jeu.jeu_nbennemi==0)
			{
                vie=tankGetVie(&sdljeu->jeu.jeu_tank);
                vie=vie+1;
                score=jeuGetScore(&sdljeu->jeu);
                niv++;
                sdljeuInit(sdljeu,niv);
                sdljeu->jeu.jeu_tank.tank_vie=vie;
                sdljeu->jeu.jeu_score=score;
			}
            /* on affiche le jeu sur le buffer caché */
            sdljeuAff(sdljeu);

            /* on permute les deux buffers (cette fonction ne doit se faire qu'une seule fois dans a boucle) */
            SDL_Flip(sdljeu->surface_ecran );
        }
	}
}


void sdljeuLibere(SdlJeu *sdljeu)
{
    SDL_FreeSurface(sdljeu->surface_cle);
    SDL_FreeSurface(sdljeu->surface_bonus);
	SDL_FreeSurface(sdljeu->surface_tankh);
	SDL_FreeSurface(sdljeu->surface_tankb);
	SDL_FreeSurface(sdljeu->surface_tankg);
	SDL_FreeSurface(sdljeu->surface_tankd);
	SDL_FreeSurface(sdljeu->surface_mur );
	SDL_FreeSurface(sdljeu->surface_ennemih);
	SDL_FreeSurface(sdljeu->surface_ennemib);
	SDL_FreeSurface(sdljeu->surface_ennemid);
	SDL_FreeSurface(sdljeu->surface_ennemig);
	SDL_FreeSurface(sdljeu->surface_tousEnnemi);
    SDL_FreeSurface(sdljeu->surface_tir);
    SDL_FreeSurface(sdljeu->surface_camouflage);
    SDL_FreeSurface(sdljeu->surface_acier);
    SDL_FreeSurface(sdljeu->surface_base);
    SDL_FreeSurface(sdljeu->surface_vie);
    SDL_FreeSurface(sdljeu->surface_gameover);
    SDL_FreeSurface(sdljeu->surface_ecran);
	jeuLibere(&(sdljeu->jeu));

	SDL_Quit();
}


SDL_Surface *SDL_load_image(const char* filename )
{
	/* Temporary storage for the image that's loaded */
	SDL_Surface* loadedImage = NULL;

	/* The optimized image that will be used */
	SDL_Surface* optimizedImage = NULL;

	/* Load the image */
	loadedImage = SDL_LoadBMP( filename );

	/* If nothing went wrong in loading the image */
	if ( loadedImage != NULL )
	{
		/* Create an optimized image */
		optimizedImage = SDL_DisplayFormat( loadedImage );

		/* Free the old image */
		SDL_FreeSurface( loadedImage );
	}

	/* Return the optimized image */
	return optimizedImage;
}


void SDL_apply_surface( SDL_Surface* source, SDL_Surface* destination, int x, int y )
{
	/* Make a temporary rectangle to hold the offsets */
	SDL_Rect offset;

	/* Give the offsets to the rectangle */
	offset.x = x;
	offset.y = y;

	/* Blit the surface */
	SDL_BlitSurface( source, NULL, destination, &offset );
}
